﻿using System;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
using System.Windows.Forms;
using Server.Menus;
using Server.Model;
using Server.Services;
using Server.Services.RemoteObjects;

namespace Server
{
    public class Server
    {
        private readonly ServerData _serverData;

        public Server( String serverId, bool standalone, bool gui, string serversFile )
        {
            _serverData = new ServerData( serverId, standalone, gui );
            _serverData.ServersInformation.parseServerLocation( serversFile );
        }

        private delegate void PingProtocol( bool StartAsPrimary, AutoResetEvent ev, ServerData serverData );

        private void setPrimary( )
        {
            System.Console.WriteLine( "I'm being empowered primary!" );

            _serverData.ServersInformation.PrimaryId = _serverData.ServerId;
            _serverData.ServersInformation.Primary = true;

            System.Console.WriteLine( "I'm the primary!" );
            _serverData.State = ServerState.ESTABLISHED;
            PingProtocol proto = PingManager.managePingProtocol;
            proto.BeginInvoke( true, _serverData.Terminate, _serverData, null, null );
        }

        private void setSecondary( )
        {
            _serverData.ServersInformation.PrimaryId = BullyProtocol.obtainPrimary( _serverData );
            _serverData.ServersInformation.Primary = false;

            System.Console.WriteLine( "I'm an secondary!" );
            _serverData.State = ServerState.ESTABLISHED;
            PingProtocol proto = PingManager.managePingProtocol;
            proto.BeginInvoke( false, _serverData.Terminate, _serverData, null, null );
        }

        public void Run( )
        {
            String[ ] parsedUrl = _serverData.ServersInformation.ServersLocation[ _serverData.ServerId ].Split( ':' );
            int port = Int32.Parse( parsedUrl[ parsedUrl.Length - 1 ] );

            TcpChannel tcpChannel = new TcpChannel( port );
            ChannelServices.RegisterChannel( tcpChannel, false );

            ClientToServer clientToServer = new ClientToServer( _serverData );
            ServerToServer serverToServer = new ServerToServer( _serverData );

            RemotingServices.Marshal( clientToServer, "ClientToServer" );
            RemotingServices.Marshal( serverToServer, "ServerToServer" );

            PMToServer pmToServer = new PMToServer( _serverData, clientToServer, serverToServer );
            RemotingServices.Marshal( pmToServer, "PMToServer" );

            _serverData.ServersInformation.getServersProxies( _serverData.ServerId );

            _serverData.State = ServerState.ADDREMOVE;
            _serverData.Operations.Clear( );
            if( BullyProtocol.addServer( _serverData ) )
                setPrimary( );
            else
                setSecondary( );

            if( _serverData.IsGUIPresent )
            {
                Application.EnableVisualStyles( );
                Application.SetCompatibleTextRenderingDefault( false );
                Application.Run( new ServerMainMenu( _serverData ) );
            }
            else
            {
                //Dont kill the main thread...
                while( true )
                {
                    Thread.Sleep( 999999 );
                }
            }
        }

        [STAThread]
        private static void Main( String[ ] args )
        {
            if( args.Length < 1 )
            {
                Console.WriteLine( "Not enough arguments provided. ENTER to quit." );
                Console.ReadLine( );
                return;
            }

            bool res;
            if( ( args.Length < 2 ) || ( !Boolean.TryParse( args[ 1 ], out res ) ) )
                res = true;

            bool gui = true;
            if( args.Length > 2 )
            {
                if( args[ 2 ] == "noGUI" )
                    gui = false;
            }

            Server server = new Server( args[ 0 ], res, gui, "..\\..\\Servers.txt" );
            server.Run( );
        }
    }
}